import os
import json
import os.path

from loguru import logger
from PySide6.QtGui import QShortcut, QKeySequence, QFont, QPixmap, QMouseEvent
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from PySide6.QtNetwork import QNetworkRequest, QNetworkAccessManager
from PySide6.QtWidgets import QApplication, QWidget, QListWidgetItem
from PySide6.QtCore import QSize, Qt, QDateTime, QTimer, QUrl, QPoint

from interface.large_screen_ui import Ui_Form
from utils.redis_pubsub import RedisSubscribe

# 获取项目的当前目录
# 获取当前文件所在目录的绝对路径
current_file_dir = os.path.dirname(os.path.abspath(__file__))
# 获取项目根目录的上一级（即项目目录的父目录）
project_parent_dir = os.path.dirname(current_file_dir)
# 标准化路径（可选）
final_path = os.path.normpath(project_parent_dir)
logger_path = os.path.join(final_path, 'LOG_DIR', 'screen.log')
logger.add(logger_path, rotation="5MB", encoding="utf-8", retention="10 days")


class LargeScreenWindow(QWidget, Ui_Form):
    def __init__(self):
        super().__init__()
        self.media_player = None
        self.audio_output = None
        self.setupUi(self)  # 初始化界面QT设计师创建的界面
        self.initialization_interface()  # 这个界面是针对已有的界面做调整
        self.timer = None  # 定时器
        self.create_shortcuts()  # 创建快捷键
        self.initialization_timer()  # 初始化定时器
        self.initialization_station_info()  # 初始化工位信息
        self.redis_subscribe_thread = None  # 初始化redis订阅线程
        self.initialization_media()  # 初始化媒体播放器
        self.network_manager = QNetworkAccessManager()  # 初始化网络管理器
        self.initialization_pubsub_thread()
        self.current_vin = None

        # 新增：拖动窗口相关变量
        self.dragging = False  # 是否正在拖动
        self.drag_position = QPoint()  # 拖动起始位置

    # 新增：鼠标按下事件
    def mousePressEvent(self, event: QMouseEvent):
        # 只有左键按下时才允许拖动
        if event.button() == Qt.LeftButton:
            self.dragging = True
            # 记录鼠标相对于窗口的位置（窗口坐标）
            self.drag_position = event.position().toPoint()

    # 新增：鼠标移动事件
    def mouseMoveEvent(self, event: QMouseEvent):
        # 如果正在拖动，计算新位置并移动窗口
        if self.dragging:
            # 窗口新位置 = 鼠标全局位置 - 拖动起始位置（相对窗口）
            self.move(event.globalPosition().toPoint() - self.drag_position)

    # 新增：鼠标释放事件
    def mouseReleaseEvent(self, event: QMouseEvent):
        # 左键释放时结束拖动
        if event.button() == Qt.LeftButton:
            self.dragging = False

    def initialization_timer(self):
        """常用应用的初始化"""
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_datetime)
        self.timer.start(1000)  # 每秒更新一次

    def initialization_interface(self):
        """初始化界面"""
        self.setWindowFlags(Qt.WindowType.FramelessWindowHint)  # 新增代码
        # 设置16:9的基准尺寸
        screen = app.primaryScreen()
        resolution = screen.size()
        base_width = resolution.width()  # 或根据实际需要调整
        base_height = int(base_width * 9 / 16)
        self.setMinimumSize(QSize(base_width, base_height))
        self.resize(base_width, base_height)
        # 设置全局字体支持中文
        font = QFont("SimHei")
        self.setFont(font)

    def initialization_pubsub_thread(self):
        """初始化订阅线程"""
        self.redis_subscribe_thread = RedisSubscribe()
        self.redis_subscribe_thread.signal.connect(self.refresh_interface)  # 获取线程订阅数据
        self.redis_subscribe_thread.start()  # 启动线程

    def create_shortcuts(self):
        # 创建"退出"快捷键，Ctrl+Q
        QShortcut(QKeySequence("Ctrl+Q"), self).activated.connect(self.close)

    def update_datetime(self):
        """获取当前日期和时间"""
        current_datetime = QDateTime.currentDateTime()
        # 更新日期
        self.dateLabel.setText(current_datetime.toString("yyyy-MM-dd dddd"))
        # 更新时间
        self.timeLabel.setText(current_datetime.toString("hh:mm:ss"))

    def refresh_interface(self, message: dict):
        """刷新界面数据"""
        if not message:
            return
        font = QFont()
        font.setPointSize(30)
        if message.get('process') == 'start':
            self.start_detection(message, font)

        if message.get('process') == 'end':
            self.end_detection(message, font)

    def start_detection(self, message: dict, font: QFont):
        """检测开始"""
        current_vin = message.get('current_vin', '')
        self.current_vin = current_vin
        queue_list = message.get('queue_list', [])  # 确保获取的是列表
        self.waitAcquisitionlistWidget.setFont(font)
        self.clear_added_items(self.waitAcquisitionlistWidget)
        self.OCRVINTextLabel.clear()
        self.VINPhotoLabel.clear()
        for item_text in queue_list:
            item = QListWidgetItem(item_text)
            item.setTextAlignment(Qt.AlignCenter)
            self.waitAcquisitionlistWidget.addItem(item)
        self.currentAcquisitionVINLabel.setText(current_vin)

    def end_detection(self, message: dict, font: QFont):
        """检测完成刷新界面"""
        vin = message.get('vin', '')
        jpg_path = message.get('jpg_path', '')  # 获取的图片路径
        ocr_vin_judge = message.get('ocr_vin_judge', '')  # 识别判断结果
        ocr_vin_result = message.get('ocr_vin_result', '')  # 判断结果文本
        captured_count = message.get('captured_count', 0)  # 采集数量
        captured_list = message.get('captured_list', [])  # 已采集列表显示5台车
        abnormal_count = message.get('abnormal_count', 0)  # 异常数量
        abnormal_list = message.get('abnormal_list', [])  # 异常数据显示5台车的
        lost_count = message.get('lost_count', 0)  # 漏采数量
        lost_list = message.get('lost_list', [])  # 漏采、异常数据显示5
        # 1.先清除原来的数据
        list_widget_list = [self.hasAcquisitionlistListWidget, self.lostListWidget]
        [self.clear_added_items(item) for item in list_widget_list]
        # 显示采集数量
        self.acquisitionCountLabel.setText(f'<span style="color: #1d953f;">{captured_count}</span>')
        self.hasAcquisitionlistListWidget.setFont(font)
        for item_text in captured_list:
            item = QListWidgetItem(item_text)
            item.setTextAlignment(Qt.AlignCenter)
            self.hasAcquisitionlistListWidget.addItem(item)
        # 显示异常数量
        self.abnormalDataLabel.setText(f'<span style="color: #red;">{abnormal_count}</span>')
        # 显示漏采数量
        self.missedDataLabel.setText(f'<span style="color: #ffd400;">{lost_count}</span>')
        self.lostListWidget.setFont(font)
        lost_abnormal_list = abnormal_list + lost_list
        for item_text in lost_abnormal_list:
            item = QListWidgetItem(item_text)
            item.setTextAlignment(Qt.AlignCenter)
            self.lostListWidget.addItem(item)
        if ocr_vin_judge == '1':
            self.OCRVINTextLabel.setText(f'<span style="color: #1d953f;">{ocr_vin_result}</span>')
        else:
            self.OCRVINTextLabel.setText(f'<span style="color: red;">{ocr_vin_result}</span>')
        status = message.get('status')
        if status == 2:
            self.currentAcquisitionVINLabel.setText(f'<span style="color: #1d953f;">{self.current_vin}</span>')
        else:
            self.play_music()
        if jpg_path:
            # 调用加载网络图片的方法
            with open('config/package.json', 'r', encoding='utf-8') as read_file:
                station_info = json.loads(read_file.read())
                domain_name = station_info.get('details', {}).get('domain_name', '')
            self.load_network_image(f'{domain_name}{jpg_path}')
        else:
            self.VINPhotoLabel.setText('未获取到图片路径')
        logger.info(f'{vin}采集完成')

    def clear_added_items(self, widget, keep_initial_rows=1):
        """
        清除组件中添加的内容，保留前 keep_initial_rows 行
        :param widget: 列表组件（如 QListWidget）
        :param keep_initial_rows: 保留的初始行数（默认1行）
        """
        if not widget:
            return
        total_rows = widget.count()
        if total_rows <= keep_initial_rows:
            return  # 无需清除
        # 从第 keep_initial_rows 行开始删除（索引从0开始）
        for row in range(total_rows - 1, keep_initial_rows - 1, -1):
            widget.takeItem(row)

    def load_network_image(self, url_str):
        """异步加载网络图片并显示"""
        url = QUrl(url_str)
        if not url.isValid():
            self.VINPhotoLabel.setText('无效的URL')
            return

        request = QNetworkRequest(url)
        reply = self.network_manager.get(request)

        # 异步处理网络请求结果
        def handle_finished():
            image_data = reply.readAll()
            pixmap = QPixmap()
            if pixmap.loadFromData(image_data):
                # 缩放图片以适应Label（保持比例）
                scaled_pixmap = pixmap.scaled(
                    self.VINPhotoLabel.size(),
                    Qt.KeepAspectRatio,
                    Qt.SmoothTransformation
                )
                self.VINPhotoLabel.setPixmap(scaled_pixmap)
                self.VINPhotoLabel.setText('')  # 清除文本
            reply.deleteLater()

        reply.finished.connect(handle_finished)

    def initialization_station_info(self):
        """加载工位信息（增加异常处理）"""
        try:
            with open('config/package.json', 'r', encoding='utf-8') as read_file:
                station_info = json.loads(read_file.read())
                station_code = station_info.get('details', {}).get('station_code', '')
                station_name = station_info.get('details', {}).get('station_name', '')
                self.stationCodeLabel.setText(station_code)
                self.stationNameLabel.setText(station_name)
        except (FileNotFoundError, json.JSONDecodeError) as e:
            logger.error('读取工位配置失败: {e}')
            self.stationCodeLabel.setText("配置缺失")
            self.stationNameLabel.setText("配置缺失")

    def play_music(self):
        """播放音乐（跨平台路径优化）"""
        music_path = os.path.join('music', '采集失败音效.mp3')
        if not os.path.exists(music_path):
            return
        media_content = QUrl.fromLocalFile(music_path)
        self.media_player.setSource(media_content)
        self.media_player.play()

    def closeEvent(self, event):
        """重写关闭事件以终止Redis订阅线程"""
        if self.redis_subscribe_thread:
            self.redis_subscribe_thread.is_running = False  # 需在RedisSubscribe类中添加此标志
            self.redis_subscribe_thread.wait()  # 等待线程结束
            logger.info('Redis订阅线程已关闭')
        super().closeEvent(event)

    def initialization_media(self):
        self.media_player = QMediaPlayer()
        self.audio_output = QAudioOutput()
        self.media_player.setAudioOutput(self.audio_output)
        self.audio_output.setVolume(0.5)


if __name__ == '__main__':
    app = QApplication([])
    window = LargeScreenWindow()
    window.show()
    app.exec()
